import type {
  MenuDataItem,
  BasicLayoutProps as ProLayoutProps,
  Settings,
} from '@ant-design/pro-layout';
import { FC, useMemo } from 'react';
import { useRef, useEffect } from 'react';
import { Result, Button } from 'antd';
import Authorized from '@/utils/Authorized';
import { Link, connect, history, Dispatch, useIntl } from 'umi';
import { GithubOutlined } from '@ant-design/icons';
import ProLayout, { DefaultFooter, SettingDrawer } from '@ant-design/pro-layout';
import RightContent from '@/components/GlobalHeader/RightContent';
import type { ConnectState } from '@/models/connect';
import { getMatchMenu } from '@umijs/route-utils';
import logo from '../assets/logo.svg';

// 定义无权限组件
const noMatch = (
  <Result
    status={403}
    title="403"
    subTitle="对不起，您没有权限访问该页面。"
    extra={
      <Button type="primary">
        <Link to="/user/login">登录</Link>
      </Button>
    }
  />
)

// 配置属性
export type BasicLayoutProps = {
  breadcrumbNameMap: Record<string, MenuDataItem>;
  route: ProLayoutProps['route'] & {
    authority: string[]
  }
  settings: Settings;
  dispatch: Dispatch;
} & ProLayoutProps;
export type BasicLayoutContext = { [K in 'location']: BasicLayoutProps[K] & {
  breadcrumbNameMap: Record<string, MenuDataItem>
} }

/** Use Authorized check all menu item */

const menuDataRender = (menuList: MenuDataItem[]): MenuDataItem[] => menuList.map(item => {
  const localItem = {
    ...item,
    children: item.children ? menuDataRender(item.children) : undefined
  }
  return Authorized.check(item.authority, localItem, null) as MenuDataItem;
})

const defaultFooterDom = (
  <DefaultFooter
    copyright={`${new Date().getFullYear()} Meatball 9.体验技术出品`}
    links={[
      {
        key: 'Meatball 9. Apps',
        title: 'Meatball 9. Apps',
        href: 'https://pro.ant.design',
        blankTarget: true
      },
      {
        key: 'gitee',
        title: <GithubOutlined />,
        href: 'https://gitee.com/eight_oclock_classroom/learn-ts.git',
        blankTarget: true
      },
      {
        key: 'Meatball 9.',
        title: 'Meatball 9.',
        href: 'https://ant.design',
        blankTarget: true
      }
    ]}
  />
)

const BasicLayout: FC<BasicLayoutProps> = (props) => {
  const {
    dispatch,
    children,
    settings,
    location = {
      pathname: '/'
    }
  } = props;
  /**
   * useRef返回一个可变的ref对象，其.current属性被初始化为传递的参数(initialValue)。返回的对象将在组件的整个生命周期内持久存在。
   * 注意，useRef()不仅适用于ref属性。它有助于保持任何可变值，类似于在类中使用实例字段的方式。
   */
  const menuDataRef = useRef<MenuDataItem[]>([]);
  /**
   * 接受包含命令式的、可能有效的代码的函数。
   * @param effect -命令式函数，可以返回一个清理函数
   * @param deps -如果存在，只会在列表中的值改变时激活。
   * @version — 16.8.0
   * @see — https ://reactjs.org/docs/hooks-reference.html#useeffect
   */
  useEffect(() => {
    if (dispatch) {
      dispatch({
        type: 'user/fetchCurrent'
      })
    }
  }, [])

  /** 初始化变量 */
  const handleMenuCollapse = (payload: boolean): void => {
    if(dispatch) {
      dispatch({
        type: 'global/changeLayoutCollapsed',
        payload
      })
    }
  }

  // 获取子集权限
  const authorized = useMemo(
    () => 
      getMatchMenu(location.pathname || '/', menuDataRef.current).pop() || {
        authority: undefined
      },
      [location.pathname]
  )
  const { formatMessage } = useIntl();
  return (
    <>
      <ProLayout
        logo={logo}
        formatMessage={formatMessage}
        {...props}
        {...settings}
        onCollapse={handleMenuCollapse}
        onMenuHeaderClick={() => history.push('/')}
        menuItemRender={(menuItemProps, defaultDom) => {
          if(
            menuItemProps.isUrl ||
            !menuItemProps.path ||
            location.pathname === menuItemProps.path
          ) {
            return defaultDom;
          }
          return <Link to={menuItemProps.path}>{defaultDom}</Link>
        }}
        breadcrumbRender={(routers = []) => [
          {
            path: '/',
            breadcrumbName: '首页'
          },
          ...routers
        ]}
        itemRender={(route, params, routes, paths) => {
          const first = routes.indexOf(route) === 0;
          return first ? (
            <Link to={paths.join('/')}>{route.breadcrumbName}</Link>
          ) : (
            <span>{route.breadcrumbName}</span>
          )
        }}
        footerRender={() => {
          if (settings.footerRender || settings.footerRender === undefined) {
            return defaultFooterDom;
          }
          return null;
        }}
        menuDataRender={menuDataRender}
        rightContentRender={() => <RightContent />}
        postMenuData={menuData => {
          menuDataRef.current = menuData || [];
          return menuData || [];
        }}
      >
        <Authorized authority={authorized!.authority} noMatch={noMatch}>
          {children}
        </Authorized>
      </ProLayout>
      <SettingDrawer
        settings={settings}
        onSettingChange={config =>
          dispatch({
            type: 'settings/changeSetting',
            payload: config
          })
        }
      />
    </>
  )
}

export default connect(({ global, settings }: ConnectState) => ({
  collapsed: global.collapsed,
  settings,
}))(BasicLayout);